package velha.game;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.lcdui.*;
import velha.Menu;
import velha.VelhaMIDlet;

public class VelhaCanvas extends Canvas implements CommandListener {

    public static final boolean DEBUG = false;
    //
    public static final int MESSAGE_DISPLAY_TIME = 5000;
    public static final int SAI_DO_JOGO = 10;
    //Comandos
    private final Command COMANDO_SAIR = new Command("Sair", Command.BACK, 0);
    private final Command COMANDO_MARCAR = new Command("Marcar", Command.OK, 1);
    //Barra de status
    private final Font statusFont = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);
    private final int statusBackground = 0x000000;
    private final int statusForeground = 0xFF8000;
    private final int statusHeight = statusFont.getHeight() * 4;
    private Image imgStatus;
    //Componentes do jogo
    public final Tabuleiro tabuleiro;
    public final Lapis lapis;
    private final Juiz juiz;
    public final Player jogador;
    private final Rival rival;
    //Comunica com outro game
    public DataInputStream in;
    public DataOutputStream out;
    //
    private boolean processMessagesRunning;
    private ProcessRivalMessages processor = new ProcessRivalMessages();
    //
    private String message;
    private MessageRemover remover = new MessageRemover();

    //
    private final VelhaMIDlet midlet;

    public VelhaCanvas(VelhaMIDlet midlet, Player jogador, Rival rival) {
        setFullScreenMode(true);

        this.midlet = midlet;

        imgStatus = Image.createImage(getWidth(), statusHeight);

        if (DEBUG) {
            System.out.println("Status W:" + imgStatus.getWidth() + " H:" + imgStatus.getHeight());
        }

        //Pega maior multiplo de 3 menor que getWidth()
        int resto3 = getWidth() % 3;
        int larguraTabuleiro = getWidth() - resto3;

        if (DEBUG) {
            System.out.println("Largura Tabuleiro:" + larguraTabuleiro);
        }

        //Maior multiplo de 3 menor que height restante
        int heightRestante = getHeight() - statusHeight;
        int hresto3 = heightRestante % 3;
        int alturaTabuleiro = heightRestante - hresto3;

        if (DEBUG) {
            System.out.println("Altura Tabuleiro:" + alturaTabuleiro);
        }

        this.tabuleiro = new Tabuleiro(this, larguraTabuleiro, alturaTabuleiro);

        this.tabuleiro.x = 0;
        this.tabuleiro.y = statusHeight + 1;

        if (DEBUG) {
            System.out.println("Tabuleiro X:" + tabuleiro.x + " Y:" + tabuleiro.y);
        }

        this.tabuleiro.reajustaLugares();

        this.lapis = new Lapis();
        this.lapis.game = this;
        this.lapis.lugar = tabuleiro.lugar[Tabuleiro.getIndice(2, 2)];

        this.juiz = new Juiz(tabuleiro);
        this.jogador = jogador;

        this.rival = rival;

        addCommand(COMANDO_SAIR);
        addCommand(COMANDO_MARCAR);
        setCommandListener(this);

        renderStatus();
    }

    protected void paint(Graphics g) {
        g.setColor(0xFFFFFF);
        g.fillRect(0, 0, getWidth(), getHeight());

        g.drawImage(imgStatus, 0, 0, 0);

        tabuleiro.draw(g);

        lapis.draw(g);
    }

    private void renderStatus() {
        //Prepara conteudo
        String meusStatus = (jogador.isPlayer1 ? "1°" : "2°") + '-' + jogador.caracter + " Venceu: " + ' ' + jogador.pontos + "x";
        String statusRival = "Ele venceu: " + rival.pontos + "x";

        //Pega referencia de Graphics
        Graphics g = imgStatus.getGraphics();

        //Limpa a area com a cor de fundo
        g.setColor(statusBackground);
        g.fillRect(0, 0, imgStatus.getWidth(), imgStatus.getHeight());

        //Muda a cor para a cor do texto
        g.setColor(statusForeground);

        //Desenha meu status
        g.drawString(meusStatus, 0, 0, 0);

        //Desenha status dele na proxima linha
        g.drawString(statusRival, 0, statusFont.getHeight(), 0);

        //Desenha mensagem
        if (message != null) {
            g.drawString(message, 0, statusFont.getHeight() * 2, 0);
        }
    }

    public void startMessageProcessing(){
        Thread processMessagesThread = new Thread(processor);
        processMessagesThread.start();
    }
    
    private void displayMessage(String message) {
        this.message = message;
        renderStatus();
        repaint();
        Thread removerThread = new Thread(remover);
        removerThread.start();
    }

    private class MessageRemover implements Runnable {

        public void run() {
            
            try {
                Thread.sleep(MESSAGE_DISPLAY_TIME);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            
            message = null;
            renderStatus();
            repaint();
        }
    }

    private class ProcessRivalMessages implements Runnable {

        public void run() {
            processMessagesRunning = true;
            while (processMessagesRunning) {
                try {
                    int nume = in.readInt();

                    //Casa marcada
                    if (nume < 10) {
                        Lugar tempL = tabuleiro.lugar[nume];
                        tempL.marca = rival.caracter;
                        lapis.isVisivel = true;
                        juiz.verifica(VelhaCanvas.this);
                        repaint();
                    }

                    //Ele saiu
                    if (nume == 10) {
                        processMessagesRunning = false;
                        endGame();
                        Alert alerta = new Alert("Fim", "Ele saiu."/*  é galinha."*/, null, AlertType.ALARM);
                        alerta.setTimeout(Alert.FOREVER);
                        midlet.getDisplay().setCurrent(alerta, new Menu(midlet));
                    }

                } catch (IOException ex) {
                    processMessagesRunning = false;
                    endGame();
                    Alert alerta = new Alert("Fim", "Ele saiu."/*  é galinha."*/, null, AlertType.ALARM);
                    alerta.setTimeout(Alert.FOREVER);
                    midlet.getDisplay().setCurrent(alerta, new Menu(midlet));
                }
            }
        }
    }

    public void keyPressed(int keyCode) {

        if (!lapis.isVisivel) {
            return;
        }

        Lugar tempL = lapis.lugar;
        int novaLinha;
        int novaColuna;

        switch (getGameAction(keyCode)) {
            case UP:
                novaLinha = tempL.linha - 1;
                if (novaLinha < 1) {
                    novaLinha = 3;
                }
                lapis.lugar = tabuleiro.lugar[Tabuleiro.getIndice(novaLinha, tempL.coluna)];
                repaint();
                break;
            case DOWN:
                novaLinha = tempL.linha + 1;
                if (novaLinha > 3) {
                    novaLinha = 1;
                }
                lapis.lugar = tabuleiro.lugar[Tabuleiro.getIndice(novaLinha, tempL.coluna)];
                repaint();
                break;
            case LEFT:
                novaColuna = tempL.coluna - 1;
                if (novaColuna < 1) {
                    novaColuna = 3;
                }
                lapis.lugar = tabuleiro.lugar[Tabuleiro.getIndice(tempL.linha, novaColuna)];
                repaint();
                break;
            case RIGHT:
                novaColuna = tempL.coluna + 1;
                if (novaColuna > 3) {
                    novaColuna = 1;
                }
                lapis.lugar = tabuleiro.lugar[Tabuleiro.getIndice(tempL.linha, novaColuna)];
                repaint();
                break;
            case FIRE:
                fire();
                break;
        }
    }

    
    private void fire() {
        if (lapis.escreve()) {
            juiz.verifica(this);
            repaint();
        }
    }

    private void minimax(){
    	
    }
    
    public void commandAction(Command c, Displayable d) {
        if (c == COMANDO_SAIR) {
            processMessagesRunning = false;
            endGame();
            midlet.getDisplay().setCurrent(new Menu(midlet));
        }

        if (c == COMANDO_MARCAR) {
            fire();
        }

    }

    public void ganhou() {
        jogador.pontos++;
        renderStatus();
        lapis.isVisivel = true;
        jogador.isPrimeiro = true;
        displayMessage("Você venceu !");
    }

    public void perdeu() {
        rival.pontos++;
        renderStatus();
        lapis.isVisivel = false;
        jogador.isPrimeiro = false;
        displayMessage("Você perdeu !");
    }

    public void empate() {
        if (jogador.isPrimeiro) {
            lapis.isVisivel = true;
        } else {
            lapis.isVisivel = false;
        }
        displayMessage("Empate !");
    }

    public void endGame() {
        try {
            out.writeInt(10);
            out.flush();
        } catch (IOException ex) {
        }
        try {
            out.close();
        } catch (IOException ex) {
        }
        try {
            in.close();
        } catch (IOException ex) {
        }
    }
}
